/**
 * 判断是否为对象
 *
 * @param {Object} val 待判断的对象
 * @returns {boolean} true || false
 */
export function isObject(val) {
  // console.log(val, Object.prototype.toString.call(val));
  return Object.prototype.toString.call(val) === "[object Object]";
}

/**
 * 防抖
 */
export function debounce(fun, wait = 50) {
  let timer;
  return function (...args) {
    console.log("args", ...args);
    // 有新的请求进来就干掉原来的计时器，重新开始计时
    if (timer) {
      clearTimeout(timer);
    }
    // 计时器完成，执行函数
    timer = setTimeout(() => {
      // 使用call或者apply的方式，执行当前闭包中缓存的事件函数，并将参数传出
      // console.log(this);
      fun.apply(this, args);
    }, wait);
  };
}

/**
 * 一个简单的节流函数
 * @param {function} fun 需要执行的函数
 * @param {number} time 指定的时间周期长度（毫秒）
 */
export function easyThrottle(fun, time = 500) {
  console.log(fun, time);
  // 用于缓存当前时间，以判断上一次这个方法执行到现在已经用了多久
  let previous = 0;
  // 返回一个闭包函数
  return function (...args) {
    // 当前时间
    let now = Date.now();
    // 上次执行时间到当前时间是否已经允许再次执行
    if (now - previous > time) {
      // 执行函数
      fun.apply(this, args);
      // 修改上次时间为当前时间，下一次进入时就跟当前时间比较
      previous = now;
    }
  };
}

export function easy(fun, time = 300) {
  let prevnum = 0;
  return function (...args) {
    let now = Date.now();
    if (now - prevnum > time) {
      fun.apply(this, args);
      prevnum = now;
    }
  };
}

export function throttle(
  fun,
  wait = 500,
  option = { leading: false, tralling: true }
) {
  // 如果第一次 和 最后一次都为false可能会出现用户操作完全无响应的情况
  if (!option.leading && !option.tralling) {
    option.tralling = true;
  }

  // 缓存一个定时器，便于执行最后一次任务
  let timer;

  // 用于缓存上一次执行回调的时间
  let previous = 0;

  /**
   * 抛出闭包函数 进行判断
   */
  return function (...args) {
    // 获取当前时间戳
    let now = Date.now();

    // 记录当前时间戳与上一次时间戳的时间差
    let remaining;

    // 先判断是否为第一次进入 previous===0 时说明是第一次执行  执行之后previous就为当前时间戳
    if (previous === 0) {
      previous = now;
      // 判断是否需要首次调用

      // 如果不需要 等待一个 时间周期
      if (!option.leading) {
        remaining = wait;
      } else {
        remaining = 0;
      }
    } else {
      remaining = wait - (now - previous);
    }

    // 根据等待时间进行判断
    if (remaining <= 0) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }

      previous = now;
      fun.apply(this, args);
    }
    // 如果没有等待时间以后 判断是否需要最后一次执行
    else if (option.tralling) {
      clearTimeout(timer);

      timer = setTimeout(() => {
        previous = 0;
        clearTimeout(timer);
        timer = null;
        fun.apply(this, args);
      }, remaining);
    }
  };
}

export function jieliu(fun, wait = 1000) {
  let timer;

  // 用于缓存上一次的获取回调时间
  let previous = 0;
  return function (...args) {
    let now = Date.now();

    // 记录当前时间戳与上一次时间戳的时间差
    let remaining;
    // console.log(now);

    // 判断是不是第一次执行
    if (previous === 0) {
      // 如果第一次执行 就让remaining 等于回调函数的等待时间
      remaining = wait;
    } else {
      // 否则
      remaining = wait - (now - previous);
    }

    // 通过时间差进行判断
    if (remaining <= 0) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }

      previous = now;
      fun.apply(this, args);
    } else {
      clearTimeout(timer);

      timer = setTimeout(() => {
        previous = 0;
        clearTimeout(timer);
        timer = null;
        fun.apply(this, args);
      }, remaining);
    }
  };
}

export function jie(
  fun,
  wait = 500,
  options = { leading: false, tralling: true }
) {
  let timer;

  // 记录上一次时间
  let previous = 0;

  // 判断是否有首次和最后一次执行 如果都没有默认执行一个
  if (!options.leading && !options.tralling) {
    console.log("必须有一次执行");
    options.tralling = true;
  }

  return function (...arges) {
    // 当前时间
    let now = Date.now();
    // 当前时间与上一次时间的差
    let remaining;

    //判断是否第一次进入
    if (previous === 0) {
      // 记录当前时间
      previous = now;

      // 首次执行判断
      if (options.leading) {
        // 如果需要首次执行 直接设置等待时间为0  就会直接执行
        remaining = 0;
      } else {
        // 如果不需要首次执行 就让等待时间 = 当前传进来的等待时间
        remaining = wait;
      }
    } else {
      // 如果不是首次执行   等待时间 =  默认等待时间 - （当前时间 - 上次执行的时间）
      remaining = wait - (now - previous);
    }

    // 通过等待时间进行判断是否直接执行  如果等待时间大于remaining 说明上次执行还未结束 所以不用操作
    // 如果 等待时间remaining <=0 说明已经 距离上次执行已经超过wait 就可以执行下一次
    if (remaining <= 0) {
      // 防止数据错误 每次清除
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }

      // 重新记录当前时间 与 首次执行一样
      previous = now;
      fun.apply(this, arges);
    } else if (options.tralling) {
      // 如果需要最后一次执行 先清除原来的timer
      clearTimeout(timer);

      // 设置定时器 在 等待时间<0时触发最后一次执行 触发后清除
      timer = setTimeout(() => {
        clearTimeout(timer);
        timer = null;
        previous = 0;
        fun.apply(this, arges);
      }, remaining);
    }
  };
}
